package com.tengju.user.infrastructure.shared;

import cn.hutool.core.util.ReflectUtil;
import com.tengju.user.domain.annotation.ElasticCryptEntity;
import com.tengju.user.domain.shared.AESUtil;
import com.tengju.user.domain.shared.CastUtil;
import com.tengju.user.domain.shared.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author: 李大仙
 * @date: 2021/8/30 7:23 下午
 */
@Slf4j
@Aspect
@Component
public class ElasticDecryptAction {

    @Pointcut("@annotation(com.tengju.user.domain.annotation.ElasticDecrypt)")
    private void elasticDecryptPointcut() {
    }

    @Around(value = "elasticDecryptPointcut()")
    public Object elasticDecryptAround(ProceedingJoinPoint pjp) {
        Object obj = null;
        try {
            obj = pjp.proceed();
            decrypt(obj);
        } catch (Throwable e) {
            log.error("es解密异常," + CastUtil.castString(obj),e);
        }
        return obj;
    }

    public void decrypt(Object obj) throws IllegalAccessException {
        if (obj instanceof Collection) {
            decryptCollection(obj);
        } else if (obj instanceof Page) {
            List<?> objectList = ((Page<?>) obj).toList();
            for (Object singleObj : objectList) {
                decrypt(singleObj);
            }
        } else if (obj instanceof Map){
            Collection<?> objectList = ((Map<?, ?>) obj).values();
            for (Object singleObj : objectList) {
                decrypt(singleObj);
            }
        } else {
            decryptSingle(obj);
        }

    }

    private void decryptCollection(Object obj) throws IllegalAccessException {
        if (obj == null) {
            return;
        }
        if (obj instanceof Collection) {
            for (Object singleObj : ((Collection<?>) obj)) {
                decryptSingle(singleObj);
            }
        }
    }

    private void decryptSingle(Object obj) throws IllegalAccessException {
        if (obj == null) {
            return ;
        }
        Class<?> clazz = obj.getClass();
        if (!clazz.isAnnotationPresent(ElasticCryptEntity.class)) {
            return;
        }
        ElasticCryptEntity cryptEntity = clazz.getAnnotation(ElasticCryptEntity.class);
        String[] cryptFieldNames = cryptEntity.cryptFields();
        if (cryptFieldNames.length == 0) {
            return;
        }
        for (String cryptFieldName : cryptFieldNames) {
            Field field = ReflectUtil.getField(clazz, cryptFieldName);
            if (field == null) {
                continue;
            }
            field.setAccessible(Boolean.TRUE);
            if (field.get(obj) == null) {
                continue;
            }
            Object val = field.get(obj);
            if (!(val instanceof String)) {
                log.info("es解密只支持字符串类型,{}",val);
                continue;
            }
            if (StringUtils.isBlank(val.toString())) {
                continue;
            }
            String decryptVal = AESUtil.decrypt(Constant.ELASTIC_ENCRYPT_KEY, val.toString());
            field.set(obj,decryptVal);
        }
    }

}
